<template>
	<div class="_luo-canvas_">
		<canvas ref="backgroundElRef" class="_luo-canvas_layer" data-role="background" data-seq="background"></canvas>
	</div>
</template>

<script setup>
	import { ref, reactive, onMounted, unref } from 'vue';
	import Source_bgImage$0 from './source/image/bgImg$0.jpg';
	
	const backgroundElRef = ref();
	
	const Util = {
		adaptCanvasHidpi(el) {
			const rect = el.getBoundingClientRect();
			const pixelRatio = Util.calcCanvasPixelRatio(el);
			el.width = rect.width * pixelRatio;
			el.height = rect.height * pixelRatio;
			return { pixelRatio, width: el.width, height: el.height };
		},
		calcCanvasPixelRatio(target) {
			const ctx = target?.tagName == 'CANVAS' ? target.getContext('2d') : target;
			return (window.devicePixelRatio || 1) / (ctx.backingStorePixelRatio || 1);
		},
		loadImage(src, width, height) {
			return new Promise((resolve, reject) => {
				const image = new Image(width, height);
				image.addEventListener('load', () => resolve(image));
				image.addEventListener('error', (e) => reject(e));
				image.src = src;
			})
		},
		fitRect(key, clipRect, wrapRect) {
			const clipAspectRatio = clipRect.width / clipRect.height;
			const wrapAspectRatio = wrapRect.width / wrapRect.height;
			let rect = {};
			switch(key) {
				case 'contain': 
					if (wrapAspectRatio > clipAspectRatio) {
						rect = { x: (wrapRect.width - wrapRect.height * clipAspectRatio) / 2, y: 0, width: wrapRect.height * clipAspectRatio, height: wrapRect.height };
						break;
					} else {
						rect = { x: 0, y: (wrapRect.height - wrapRect.width / clipAspectRatio) / 2, width: wrapRect.width, height: wrapRect.width / clipAspectRatio };
						break;
					}
				case 'cover':
					if (wrapAspectRatio > clipAspectRatio) {
						rect = { x: 0, y: (wrapRect.height - wrapRect.width / clipAspectRatio) / 2, width: wrapRect.width, height: wrapRect.width / clipAspectRatio };
						break;
					} else {
						rect = { x: (wrapRect.width - wrapRect.height * clipAspectRatio) / 2, y: 0, width: wrapRect.height * clipAspectRatio, height: wrapRect.height };
						break;
					}
				case 'fill':
					rect = { x: 0, y: 0, width: wrapRect.width, height: wrapRect.height };
					break;
				default: 
					rect = { x: 0, y: 0, width: clipRect.width, height: clipRect.height }; 
					break;
			}
			rect.sequence = [rect.x, rect.y, rect.width, rect.height];
			return rect;
		}
	}
	
	const Material = {};
	
	const Event = {
		loop: false,
		program: [],
		process() {
			requestAnimationFrame(() => {
				if (this.program.length) {
					this.loop = true;
					const currentDate = new Date();
					const list = this.program.splice(0, this.program.length);
					for (let index = 0; index < list.length; index++) {
						const item = list[index];
						if (item.status == 'wait') {
							if (item.waitTime > (item.delay || 0)) {
								item.status = 'run';
								const next = item.fn?.();
								if (next) this.program.push({ ...item, ...next });
								else item.finishFn?.();
							} else {
								item.waitTime = currentDate - item.createTime;
								this.program.push(item);
							}
						}
					}
					this.process();
				} else {
					this.loop = false;
				}
			})
		},
		add(name, fn, options) {
			this.program.push({ 
				name, 
				fn, 
				status: 'wait', 
				createTime: new Date(),
				waitTime: 0,
				delay: options?.delay || 0,
				cancelFn: options?.cancelFn,
				finishFn: options?.finishFn
			});
			if (!this.loop) this.process();
		},
		del(name) {
			const pg = this.program.find(pg => pg.name == name);
			if (pg) {
				pg.status = 'cancel';
				pg.cancelFn?.();
			}
		}
	};
	
	onMounted(() => {
		const bgEl = unref(backgroundElRef);
		const bgCtx = bgEl.getContext('2d');
		Util.adaptCanvasHidpi(bgEl);
		Promise.allSettled([
			new Promise((resolve, reject) => {
				Util.loadImage(Source_bgImage$0).then(image => {
					const matl = document.createElement('canvas');
					const name = 'bgImg$0';
					matl.width = image.naturalWidth;
					matl.height = image.naturalHeight;
					matl.getContext('2d').drawImage(image, 0, 0);
					Material[name] = matl;
					resolve({ name, matl });
				}).catch(e => reject(e))
			})
		]).then(matls => {
			bgCtx.save();
			bgCtx.globalAlpha = 0.1;
			
				bgCtx.save();
				const fitRect = Util.fitRect('cover', { width: Material.bgImg$0.width, height: Material.bgImg$0.height }, { width: bgEl.width, height: bgEl.height });
				bgCtx.drawImage(Material.bgImg$0, fitRect.x, fitRect.y, fitRect.width, fitRect.height);
				bgCtx.restore();
				
			bgCtx.restore();
		})
	})
</script>

<style lang="scss">
	._luo-canvas_ {
		position: relative;
		width: 1000px;
		aspect-ratio: 4 / 3;
		filter: drop-shadow(0 0 10px #4c4c4c);
		border-radius: 6px;
	}
	._luo-canvas_layer {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		border-radius: inherit;
	}
</style>